package com.simpou.tests.rest;

import com.simpou.tests.rest.service.RestService;
import static org.junit.Assert.assertNotNull;

import java.io.IOException;

import javax.ws.rs.core.MediaType;

import com.simpou.tests.commons.exception.TestFailedError;

import com.simpou.commons.utils.lang.ArraysHelper;
import com.sun.jersey.api.client.WebResource;

/**
 * Utilitário para testes de serialização de objetos com JAX-B usado pelo
 * JAX-RS.
 *
 * @author Jonas Pereira
 * @since 2013-03-12
 */
public class ResponseWriterTester {

    /**
     * Caminho de um recurso que retorna um objeto.
     */
    private static final String PATH = "single";

    /**
     * Servidor e cliente REST.
     */
    private final RestClientServerTester rest;

    /**
     * Configura e inicia servidor REST.
     *
     * @param port Porta do servidor REST.
     * @throws java.io.IOException Erro ao inicializar servidor ou cliente REST.
     */
    public ResponseWriterTester(final int port, final String... providerPkgs) throws IOException {
        this.rest = new RestClientServerTester(port,
                ArraysHelper.append(providerPkgs, RestService.class.getPackage().getName()));
    }

    /**
     * Interrompe servidor REST.
     */
    public void stop() {
        this.rest.stop();
    }

    /**
     * Faz uma requisição REST para obter um objeto e verifica a conversão do
     * mesmo para os tipos determinados.
     *
     * @param object Objeto a ser retornado pelo REST.
     * @param mediaTypes Tipos de converão a serem testados.
     * @throws TestFailedException Falha na obtenção e/ou conversão do objeto.
     */
    public void serialize(final Object object, final MediaType... mediaTypes) {
        RestService.setObject(object);

        if (mediaTypes.length > 0) {
            for (final MediaType mediaType : mediaTypes) {
                RestService.setMediaType(mediaType);

                Object objGetted;
                String stringObj;

                try {
                    final WebResource.Builder resource = this.rest.getResource(PATH)
                            .accept(mediaType);
                    objGetted = resource.get(object.getClass());
                    stringObj = resource.get(String.class);
                } catch (final Exception exception) {
                    throw new TestFailedError("Object " + object
                            + " cannot be parsed using " + mediaType
                            + " type. Cause: ", exception);
                }

                assertNotNull(stringObj);
                //assertEquals(object, objGetted);
            }
        } else {
            try {
                this.rest.getResource(PATH).get(object.getClass());
            } catch (final Exception exception) {
                throw new TestFailedError("Object " + object
                        + " cannot be parsed.", exception);
            }
        }
    }
}
